﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using ArcannEngine.Entities;
using ArcannEngine.Render;
using ArcannEngine.GeometricPrimitives;

namespace ArcannEngine.Components
{
    public class RenderComponent : Component
    {
        // Skala renderowanego obiektu
        private Matrix scaleMatrix = Matrix.Identity;

        private RenderDescription description;
        public RenderDescription Description
        {
            get { return description; }
            set { description = value; }
        }

        protected override string GetName()
        {
            return "Render";
        }

        // Przeciazenie konstruktorow: rysujemy albo model albo prymityw
        public RenderComponent(Entity ParentEntity, String Modelname)
            : base(ParentEntity)
        {
            Initialize();
            LoadModel(Modelname);
            ParentEntity.Model = description.Model;
        }

        public RenderComponent(Entity ParentEntity, GeometricPrimitiveType primitive)
            : base(ParentEntity)
        {
            Initialize();
            LoadPrimitive(primitive);
        }

        private void LoadModel(String ModelName)
        {

            description.model = this.Parent.Manager.Content.Load<Model>(ModelName);
        }
        // Jesli jest potrzeba rysowania prymitywow o okreslonych wymiarach
        // to dopisac odpowiednie wartosci tutaj, ew. dorobic odpowiednie funkcje
        private void LoadPrimitive(GeometricPrimitiveType primitive)
        {
            switch (primitive)
            {
                case GeometricPrimitiveType.Cube:
                    description.geoPrim = new CubePrimitive(this.Parent.Manager.Game.GraphicsDevice);
                    break;
                case GeometricPrimitiveType.Sphere:
                    description.geoPrim = new SpherePrimitive(this.Parent.Manager.Game.GraphicsDevice);
                    break;
                case GeometricPrimitiveType.Cylinder:
                    description.geoPrim = new CylinderPrimitive(this.Parent.Manager.Game.GraphicsDevice);
                    //description.geoPrim = new CylinderPrimitive(this.Parent.Manager.Game.GraphicsDevice, 3.0f, 1.0f, 10);
                    break;
                case GeometricPrimitiveType.Torus:
                    description.geoPrim = new TorusPrimitive(this.Parent.Manager.Game.GraphicsDevice);
                    break;
                case GeometricPrimitiveType.Teapot:
                    description.geoPrim = new TeapotPrimitive(this.Parent.Manager.Game.GraphicsDevice);
                    break;
                default:
                    throw new Exception("LoadPrimitive does not handle this type of GeometricPrimitive. Was a new primitive type made and not handled here?");
            }
        }

        protected override void Initialize()
        {
            description = new RenderDescription();

            description.worldTransform = this.scaleMatrix * this.Parent.rotation * Matrix.CreateTranslation(this.Parent.position);

            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            // W przyszlosci dobrze byloby obslugiwac zmiany pozycji/rotacji obiektu za pomoca listenera, a nie w kazdym updacie
            description.worldTransform = this.scaleMatrix * this.Parent.rotation * Matrix.CreateTranslation(this.Parent.position);
        }

        public override void Draw(GameTime gameTime, List<RenderDescription> renderDescriptions)
        {
            // Mozna dorobic obsluge bryly widzenia
            renderDescriptions.Add(description);
        }

    }
}
